// ManualBot.cpp : Defines the entry point for the console application.
//

#define _CRT_SECURE_NO_DEPRECATE 1
#include "stdafx.h"
#include "SittingDuckAgent.h"
#include "Visualizer.h"
#include "RecieveRoleAssignmentState.h"
#include "EnemyFlagStolenState.h"
#include "RetrieveFallenFlag.h"
#include "TimeHelper.h"

#include <conio.h>   //for getch(), needed in wait_for_key()
#include <windows.h> //for Sleep()

void sleep(int i) { Sleep(i*1000); }
void process_args(int argc, char* argv[]);

int _tmain(int argc, char* argv[]) {
	process_args(argc, argv);
	
	BZRC* remote = Remote::instance();
	World* world = World::instance();

	world->init();

	std::vector<Agent> agents;
	for(unsigned int i = 0; i < world->tanks().size(); i ++){
		agents.push_back(Agent(&world->tanks()[i]));
	}

	for(unsigned int i = 0; i < world->tanks().size(); i ++){
		agents[i].setState(new RecieveRoleAssignmentState());
	}

	
	Visualizer visualizer;
	visualizer.init(argc, argv);
	visualizer.show();
	

	vector<Command> commands;

	bool hasFlag = false;
	int activeSeeker = -1;
	bool seekerAlive = true;

	while (true) {
		commands.clear();
		long start = TimeHelper::GetTime();

		if(world->TeamMemberHasFlag()){
			if(!hasFlag){
				//TODO: Add EnemyFlagStolenState
				hasFlag = true;
				for(int i = 0; i< agents.size(); i ++){
					tank_t* tank = agents[i].getTank();
					if(tank->flag.compare("-") == 0){
						agents[i].setState(new EnemyFlagStolenState());
					}
				}
			}
		}
		else{
			if(hasFlag || !seekerAlive){
				hasFlag = false;
				//TODO: Add get dropped flag
				for(int i = 0; i < agents.size(); i ++){
					tank_t* tank = agents[i].getTank();
					if(tank->status.compare("alive") == 0){
						activeSeeker = i;
						seekerAlive = true;
						agents[i].setState(new RetrieveFallenFlag());
						break;
					}
				}
			}else if(activeSeeker >= 0){
				tank_t* tank = agents[activeSeeker].getTank();
				if(tank->status.compare("alive") != 0){
					seekerAlive = false;
					activeSeeker = -1;
				}
			}
		}

		// Get commands for each of the tanks
		for(unsigned int i = 0; i < agents.size(); i ++){
			commands.push_back(agents[i].GetCommand());
		}

		commands.push_back(world->update());

		remote->do_commands(commands);

		world->updateKalmanFilters();

		cout << "Loop Time: " << TimeHelper::TimeSince(start) << "ms" << endl;
	}

	cout << "Press <ENTER> to quit";
	getch();

	return 0;
}

void process_args(int argc, char* argv[]) {
	string server;
	int port;

	if(argc < 2) {
		cout << "server: ";
		cin >> server;
	}
	else {
		server = argv[1];
	}
    if(argc < 3) {
		cout << "port: ";
		cin >> port;
	}
	else {
        port = atoi(argv[2]);
    }

	cout << "Connecting...";
	Remote::init(server, port, false);

	if (!Remote::instance()->GetStatus()) {
		cout << endl << "Unable to contact server" << endl;
		exit(1);
	}
	else {
		cout << " Success!" << endl;
	}
}